package uk.co.agileworks.bidpirate.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Index;

@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "ITEM_ITEMNUMBER", "USER_ID" }) })
public final class Bid implements Serializable {

	private static final long serialVersionUID = 1L;
	private static final String HIDDEN_FIELD = "itemNumberOrUrl";

	@Id
	@GeneratedValue
	private Long id;
	private Double maxBid;
	@Column(name = "GROUP_TOKEN")
	private String group;
	@Cascade(value = CascadeType.SAVE_UPDATE)
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "ITEM_ITEMNUMBER")
	private Item item;
	@Cascade(value = CascadeType.SAVE_UPDATE)
	@ManyToOne
	@JoinColumn(name = "USER_ID")
	private User user;
	@Index(name = "BID_STATUS")
	@Enumerated(EnumType.STRING)
	private Status status;
	@Transient
	private String itemNumberOrUrl;

	public String getGroup() {
		return group;
	}

	public Long getId() {
		return id;
	}

	public Item getItem() {
		return item;
	}

	public String getItemNumberOrUrl() {
		return itemNumberOrUrl;
	}

	public Double getMaxBid() {
		return maxBid;
	}

	public Status getStatus() {
		return status;
	}

	public User getUser() {
		return user;
	}
	
	public boolean isCompleted() {
		return status == Status.END || status == Status.WON || status == Status.LOST;
	}

	public boolean isInGroup() {
		return StringUtils.isNotBlank(group);
	}
	
	public boolean isUpdatable() {
		return status == Status.UNSAVED || status == Status.ACTIVE || status == Status.WATCH;
	}

	public void resetWatch() {
		if (getStatus() == Status.ACTIVE || getStatus() == Status.WATCH) {
			setStatus(getMaxBid() != null ? Status.ACTIVE : Status.WATCH);
		}
	}

	public void setGroup(String group) {
		this.group = group.toUpperCase().replaceAll("[^A-Z0-9]", "");
	}

	public void setId(Long id) {
		this.id = id;
	}

	public void setItem(Item item) {
		this.item = item;
	}

	public void setItemNumberOrUrl(String itemNumberOrUrl) {
		this.itemNumberOrUrl = itemNumberOrUrl;
	}

	public void setMaxBid(Double maxBid) {
		this.maxBid = maxBid;
	}

	public void setStatus(Status status) {
		this.status = status;
	}

	public void setUser(User user) {
		this.user = user;
	}

	@Override
	public String toString() {
		return ReflectionToStringBuilder.toStringExclude(this, HIDDEN_FIELD);
	}
}
